package org.springblade.common.utils.feishu;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lark.oapi.Client;
import com.lark.oapi.core.response.RawResponse;
import com.lark.oapi.core.token.AccessTokenType;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenReq;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenReqBody;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenResp;
import com.lark.oapi.service.bitable.v1.enums.ConditionOperatorEnum;
import com.lark.oapi.service.bitable.v1.enums.FilterInfoConjunctionEnum;
import com.lark.oapi.service.bitable.v1.model.*;
import com.lark.oapi.service.contact.v3.model.ListScopeResp;
import com.lark.oapi.service.contact.v3.resource.Scope;
import com.lark.oapi.service.drive.v1.model.DownloadMediaReq;
import com.lark.oapi.service.drive.v1.model.DownloadMediaResp;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.config.FeiShuConfiguration;
import org.springblade.common.enums.FeishuClientEnum;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.vo.feishu.FeishuDownloadVO;
import org.springblade.modules.auth.utils.FeishuUserInfo;
import org.springblade.modules.resource.builder.oss.OssBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonParser;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.im.v1.model.*;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import com.lark.oapi.core.request.RequestOptions;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;

/**
 * @Description 飞书工具类
 * @Author ysq
 * @Date 2024/03/27
 **/
@Slf4j
@Component
public class FeiShuUtil {

	@Autowired
	private FeiShuConfiguration feiShuConfiguration;
	@Autowired
	private OssBuilder ossBuilder;

	/**
	 * 获取 user_access_token
	 * @param code 登录预授权码
	 * @return
	 * @throws Exception
	 */
	public FeishuUserInfo getUserAccessToken(String code) throws Exception {
		// 构建client
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.CERT);
		CreateAccessTokenResp resp = client.authen().accessToken()
			.create(CreateAccessTokenReq.newBuilder()
				.createAccessTokenReqBody(CreateAccessTokenReqBody.newBuilder()
					.code(code).grantType("authorization_code")
						.build())
				.build()
			);

		if (!resp.success()) {
			log.error(String.format("获取user_access_token失败，code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
			throw new ServiceException("获取user_access_token失败");
		}

        return JSONUtil.toBean(Jsons.DEFAULT.toJson(resp.getData()), FeishuUserInfo.class);
	}

	/**
	 * 获取 managers ,默认参数, OpenID
	 */
	public List<String> getOpenIdsByDefaultParam() throws Exception {
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.CERT);
		Scope scope = client.contact().v3().scope();
		ListScopeResp list = scope.list(null);
		log.info(Jsons.DEFAULT.toJson(list));
		String[] userIds = list.getData().getUserIds();
		return new ArrayList<>(Arrays.asList(userIds));
	}

	/**
	 * 获取 managers ,自定义参数
	 */
	public List<String> getOpenIdsByCustomParam() throws Exception {
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.CERT);
		// 发起请求
		RawResponse resp = client.get(
			"https://open.feishu.cn/open-apis/user/v4/app_admin_user/list"
			, null
			, AccessTokenType.Tenant);
		int statusCode = resp.getStatusCode();
		if(statusCode != 200){
			throw new ServiceException("获取管理员列表失败, 状态码：" + statusCode);
		}
		byte[] body = resp.getBody();
		// 将 body 转为 JsonObject
		JSONObject bodyJson = JSONObject.parseObject(new String(body));
		JSONObject data = bodyJson.getObject("data", JSONObject.class);
		JSONArray jsonArray = data.getJSONArray("user_list");
		// 遍历 JSONArray 并获取 open_id
		List<String> openIds = new ArrayList<>();
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject jsonObject = jsonArray.getJSONObject(i);
			String openId = jsonObject.getString("open_id");
			openIds.add(openId);
		}
		return openIds;
	}

	/**
	 * 飞书多维表格-根据recordId的值检索现有记录
	 * @param appToken 飞书应用token
	 * @param tableId 表格ID
	 * @param recordId 记录ID
	 * @return
	 * @throws Exception
	 */
	public String getBitableRecord(String appToken, String tableId, String recordId) throws Exception {
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.TABLE);
		GetAppTableRecordResp resp = client.bitable().v1().appTableRecord().get(GetAppTableRecordReq.newBuilder()
			.appToken(appToken).tableId(tableId).recordId(recordId).build());
		if (!resp.success()) {
			log.error(String.format("获取检索记录失败，code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
			return null;
		}

		return Jsons.DEFAULT.toJson(resp.getData());
	}

	/**
	 * 拉取飞书素材，上传到oss
	 * @param downloadParams 下载参数
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, String>> download(List<FeishuDownloadVO> downloadParams) throws Exception {
		List<Map<String, String>> fileUrlMap = new ArrayList<>();
		if (Func.isEmpty(downloadParams)) {
            return fileUrlMap;
        }

		for (FeishuDownloadVO downloadParam : downloadParams) {
			Client client = feiShuConfiguration.getClient(FeishuClientEnum.TABLE);
			DownloadMediaResp resp = client.drive().v1().media()
				.download(DownloadMediaReq.newBuilder()
					.fileToken(downloadParam.getFileToken()).extra(downloadParam.getExtra()).build());
			if (!resp.success()) {
				log.error(String.format("下载飞书素材失败，code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
				return fileUrlMap;
			}

			InputStream is = new ByteArrayInputStream(resp.getData().toByteArray());
			// 上传到oss
			BladeFile bladeFile = ossBuilder.template().putFile(resp.getFileName(), is);
			Map<String, String> fileItem = new HashMap<>(2);
			fileItem.put("fileName", bladeFile.getOriginalName());
			fileItem.put("fileUrl", bladeFile.getLink());
			fileUrlMap.add(fileItem);
		}

		return fileUrlMap;
    }

	/**
	 * 根据planId获取飞书多维表格的记录ID
	 * @param appToken
	 * @param tableId
	 * @param fieldName 飞书表格字段名称
	 * @param planId 工单id
	 * @return 表格记录ID
	 * @throws Exception
	 */
	public String getRecordIdByPlanId(String appToken, String tableId, String fieldName, Long planId) throws Exception {
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.TABLE);
		Condition[] conditions = new Condition[1];
		conditions[0] = Condition.newBuilder().fieldName(fieldName).operator(ConditionOperatorEnum.OPERATORIS).value(new String[]{String.valueOf(planId)}).build();
		SearchAppTableRecordResp resp = client.bitable().v1().appTableRecord().search(SearchAppTableRecordReq
			.newBuilder().appToken(appToken).tableId(tableId).searchAppTableRecordReqBody(
				SearchAppTableRecordReqBody.newBuilder().filter(
						FilterInfo.newBuilder().conditions(conditions).conjunction(FilterInfoConjunctionEnum.CONJUNCTIONAND).build())
					.build())
			.build());

		if (!resp.success()) {
			log.error(String.format("根据planId获取飞书多维表格的记录ID失败，code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
			return null;
		}

		String respData = Jsons.DEFAULT.toJson(resp.getData());
		JSONObject jsonObject = JSON.parseObject(respData);
		if (jsonObject.getInteger("total") == 0) {
			return null;
		}
		JSONArray jsonArray = jsonObject.getJSONArray("items");
		return jsonArray.getJSONObject(0).getString("record_id");
	}

	/**
	 * 根据recordId更新飞书多维表格
	 * @param appToken
	 * @param tableId
	 * @param recordId
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public boolean updateTableByRecordId(String appToken, String tableId, String recordId, Map<String, Object> map) throws Exception {
        Client client = feiShuConfiguration.getClient(FeishuClientEnum.TABLE);
        UpdateAppTableRecordResp resp = client.bitable().v1().appTableRecord()
            .update(UpdateAppTableRecordReq.newBuilder()
                .appToken(appToken).tableId(tableId).recordId(recordId)
				.appTableRecord(AppTableRecord.newBuilder().fields(map).build()).build());
        if (!resp.success()) {
            log.error(String.format("更新飞书多维表格失败，code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
			return false;
        }
        return resp.success();
    }

	/**
	 * 根据 user_id 发送飞书卡片消息
	 */
	public String sendLarkMessageByUserId(String userId, String cardContent){
		Client client = feiShuConfiguration.getClient(FeishuClientEnum.CERT);
		// 创建请求对象
		CreateMessageReq req = CreateMessageReq.newBuilder()
			.receiveIdType("user_id")
			.createMessageReqBody(CreateMessageReqBody.newBuilder()
				.receiveId(userId)
				.msgType("interactive")
				.content(cardContent)
				.build())
			.build();
		// 发起请求
		CreateMessageResp resp = null;
		try {
			resp = client.im().v1().message().create(req);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		// 处理服务端错误
		if(!resp.success()) {
			String result = String.format("code:%s,msg:%s,reqId:%s, resp:%s",
				resp.getCode(), resp.getMsg(), resp.getRequestId(), Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8))));
			log.error(result);
			return result;
		}
		return "发送飞书卡片消息成功, resp: " + Jsons.DEFAULT.toJson(resp.getData());
	}

}
